package com.xy.webadmin.common.email.util;

import com.xy.common.core.upload.BaseUpDownloader;
import com.xy.common.core.upload.UploadResponseInfo;
import com.xy.webadmin.app.model.EmailAttachment;
import com.xy.webadmin.app.model.userEmail.UserEmailConfig;
import com.xy.webadmin.app.model.userEmail.UserEmailReceivedInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Component;

import javax.mail.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import static com.xy.application.common.constant.YesOrNo.YES;

@Slf4j
@Component
public class EmailPOP3Util {

    /**
     * 创建邮件会话并连接到服务器
     */
    public static Store connectToEmailServer(UserEmailConfig config) throws MessagingException {
        // 设置邮件服务器属性
        Properties props = new Properties();
        props.setProperty("mail.store.protocol", "pop3");
        props.setProperty("mail.pop3.host", "pop.qq.com");
        props.setProperty("mail.pop3.port", "995");
        props.setProperty("mail.pop3.ssl.enable", "true");
        props.setProperty("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
        props.setProperty("mail.pop3.socketFactory.port", "995");
        props.setProperty("mail.pop3.socketFactory.fallback", "false");
        props.setProperty("mail.debug", "true");

        // 创建会话
        Session session = Session.getInstance(props);
        Store store = session.getStore("pop3");

        // 连接邮箱服务器
        store.connect(config.getReceiveHost(), config.getEmail(), config.getAuthCode());
        boolean connected = store.isConnected();
        if (!connected) {
            throw new MessagingException("无法连接到邮箱服务器: " + config.getEmail());
        }
        log.info("成功连接到邮箱服务器: {}", config.getEmail());
        
        return store;
    }

    /**
     * 获取今天的邮件
     */
    public static List<Message> getTodayMessages(Store store) throws MessagingException {
        // 打开收件箱
        Folder inbox = store.getFolder("INBOX");
        inbox.open(Folder.READ_ONLY);

        // 获取今天的日期
        Date today = new Date();
        today.setHours(0);
        today.setMinutes(0);
        today.setSeconds(0);

        // 获取所有邮件
        int totalMessages = inbox.getMessageCount();
        log.info("邮箱中共有 {} 封邮件", totalMessages);

        // 获取所有邮件
        Message[] allMessages = inbox.getMessages(1, totalMessages);
        log.info("成功获取 {} 封邮件", allMessages.length);

        // 过滤出今天的邮件
        List<Message> todayMessages = new ArrayList<>();
        for (Message message : allMessages) {
            try {
                // 只获取必要的头部信息，不下载邮件内容
                FetchProfile profile = new FetchProfile();
                profile.add(FetchProfile.Item.ENVELOPE);
                inbox.fetch(new Message[]{message}, profile);
                Date sentDate = message.getSentDate();
                if (sentDate != null && sentDate.after(today)) {
                    todayMessages.add(message);
                    log.info("发现今天的邮件: {} - {}", message.getSubject(), sentDate);
                }
            } catch (Exception e) {
                log.error("获取邮件信息时发生错误: {}", e.getMessage());
            }
        }

        log.info("找到 {} 封今天的邮件", todayMessages.size());
        return todayMessages;
    }

    /**
     * 处理邮件内容
     *
     * @param message 邮件消息
     * @param needSaveInfo 需要保存的邮件信息对象
     * @return 处理后的邮件内容
     */
    public static String processEmailContent(Message message, UserEmailReceivedInfo needSaveInfo) throws Exception {
        StringBuilder emailContent = new StringBuilder();
        Object content = message.getContent();

        if (content instanceof String) {
            emailContent.append((String) content);
        } else if (content instanceof Multipart) {
            Multipart multipart = (Multipart) content;
            String textContent = null;
            String htmlContent = null;

            // 首先遍历一遍，找到文本和HTML内容
            for (int i = 0; i < multipart.getCount(); i++) {
                BodyPart bodyPart = multipart.getBodyPart(i);
                String contentType = bodyPart.getContentType().toLowerCase();

                if (contentType.contains("text/plain")) {
                    textContent = (String) bodyPart.getContent();
                } else if (contentType.contains("text/html")) {
                    needSaveInfo.setIsHtml(YES);
                    htmlContent = (String) bodyPart.getContent();
                } else if (contentType.contains("multipart/alternative")) {
                    // 处理嵌套的 multipart/alternative
                    Multipart nestedMultipart = (Multipart) bodyPart.getContent();
                    for (int j = 0; j < nestedMultipart.getCount(); j++) {
                        BodyPart nestedPart = nestedMultipart.getBodyPart(j);
                        String nestedContentType = nestedPart.getContentType().toLowerCase();
                        if (nestedContentType.contains("text/plain")) {
                            textContent = (String) nestedPart.getContent();
                        } else if (nestedContentType.contains("text/html")) {
                            needSaveInfo.setIsHtml(YES);
                            htmlContent = (String) nestedPart.getContent();
                        }
                    }
                }
            }

            // 优先使用HTML内容，如果没有则使用文本内容
            if (htmlContent != null) {
                emailContent.append(htmlContent);
            } else if (textContent != null) {
                emailContent.append(textContent);
            }
        }

        return emailContent.toString();
    }

    /**
     * 处理邮件附件
     *
     * @param multipart 邮件多部分内容
     * @param upDownloader 文件上传下载器
     * @param uploadFileBaseDir 上传文件基础目录
     * @return 附件列表
     */
    public static List<EmailAttachment> processAttachments(Multipart multipart, BaseUpDownloader upDownloader, String uploadFileBaseDir) throws Exception {
        List<EmailAttachment> attachments = new ArrayList<>();
        for (int i = 0; i < multipart.getCount(); i++) {
            BodyPart bodyPart = multipart.getBodyPart(i);
            String contentType = bodyPart.getContentType().toLowerCase();
            String disposition = bodyPart.getDisposition();

            // 检查是否是附件
            boolean isAttachment = (disposition != null &&
                    (disposition.equalsIgnoreCase(Part.ATTACHMENT) ||
                            disposition.equalsIgnoreCase(Part.INLINE))) ||
                    (bodyPart.getFileName() != null &&
                            !contentType.contains("text/plain") &&
                            !contentType.contains("text/html"));

            if (isAttachment) {
                try {
                    EmailAttachment attachment = new EmailAttachment();
                    String originalFileName = bodyPart.getFileName();

                    // 解码MIME编码的文件名
                    if (originalFileName != null && originalFileName.startsWith("=?")) {
                        try {
                            originalFileName = javax.mail.internet.MimeUtility.decodeText(originalFileName);
                        } catch (Exception e) {
                            log.error("解码文件名失败: {}", originalFileName, e);
                        }
                    }

                    // 确保文件名不为空
                    final String fileName = (originalFileName == null || originalFileName.trim().isEmpty())
                            ? "attachment_" + System.currentTimeMillis()
                            : originalFileName;
                    attachment.setFileName(fileName);
                    attachment.setContentType(contentType);

                    // 创建临时文件
                    File tempFile = File.createTempFile("email_attachment_", fileName);
                    try (InputStream inputStream = bodyPart.getInputStream();
                         FileOutputStream outputStream = new FileOutputStream(tempFile)) {
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = inputStream.read(buffer)) != -1) {
                            outputStream.write(buffer, 0, bytesRead);
                        }
                    }

                    // 确保临时文件存在且可读
                    if (!tempFile.exists() || !tempFile.canRead()) {
                        log.error("临时文件不存在或不可读: {}", tempFile.getAbsolutePath());
                        continue;
                    }

                    // 使用文件存储系统保存附件
                    UploadResponseInfo responseInfo = doUploadForSchedule(upDownloader, fileName, contentType, tempFile, uploadFileBaseDir);

                    // 删除临时文件
                    tempFile.delete();

                    if (responseInfo != null && !Boolean.TRUE.equals(responseInfo.getUploadFailed())) {
                        attachment.setUrl(responseInfo.getDownloadUri());
                        attachments.add(attachment);
                        log.info("成功处理附件: {}, 类型: {}", fileName, contentType);
                    } else {
                        log.error("上传附件失败: {}", responseInfo != null ? responseInfo.getErrorMessage() : "未知错误");
                    }
                } catch (Exception e) {
                    log.error("处理附件时发生错误: {}", e.getMessage(), e);
                }
            }
        }
        return attachments;
    }

    /**
     * 获取发件人地址
     *
     * @param message 邮件消息
     * @return 发件人地址
     */
    public static String getSenderAddress(Message message) throws Exception {
        Address address = message.getFrom()[0];
        Field addressField = address.getClass().getDeclaredField("address");
        addressField.setAccessible(true);
        return (String) addressField.get(address);
    }

    /**
     * 定时任务专用的文件上传方法
     */
    private static UploadResponseInfo doUploadForSchedule(
            BaseUpDownloader upDownloader,
            String fileName,
            String contentType,
            File tempFile,
            String uploadFileBaseDir) throws IOException {
        UploadResponseInfo responseInfo = new UploadResponseInfo();

        // 生成唯一的文件名
        String uniqueFileName = System.currentTimeMillis() + "_" + fileName;
        responseInfo.setFilename(uniqueFileName);

        // 设置上传路径
        String uploadPath = uploadFileBaseDir + "/" + UserEmailReceivedInfo.class.getSimpleName() + "/attachmentUrl";
        responseInfo.setUploadPath(uploadPath);

        try {
            // 创建目录
            File uploadDir = new File(uploadPath);
            if (!uploadDir.exists()) {
                uploadDir.mkdirs();
            }

            // 复制文件
            File destFile = new File(uploadPath + "/" + uniqueFileName);
            FileUtils.copyFile(tempFile, destFile);

            // 设置返回的JSON格式
            String jsonResponse = String.format(
                    "{\"name\":\"%s\",\"filename\":\"%s\",\"uploadPath\":\"%s\"}",
                    fileName,
                    uniqueFileName,
                    uploadPath
            );
            responseInfo.setDownloadUri(jsonResponse);

            return responseInfo;
        } catch (IOException e) {
            log.error("Failed to write uploaded file [" + fileName + "].", e);
            responseInfo.setUploadFailed(true);
            responseInfo.setErrorMessage("文件上传失败：" + e.getMessage());
            return responseInfo;
        }
    }
}
